/*
 * Copyright 2019-2025 the original author or authors.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.iiifi.kite.boot.common.support;

import java.io.File;

import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.web.util.UriUtils;

import com.iiifi.kite.core.result.IResultCode;
import com.iiifi.kite.core.result.Result;
import com.iiifi.kite.core.result.SystemCode;
import com.iiifi.kite.core.util.Charsets;

/**
 * 基础 controller
 *
 * @author kite@iiifi.com 花朝
 */
public interface IController {

    /**
     * redirect跳转
     *
     * @param url 目标url
     * @return 跳转地址
     */
    default String redirect(String url) {
        return "redirect:".concat(url);
    }

    /**
     * 返回成功
     *
     * @param <T> 泛型标记
     * @return Result
     */
    default <T> Result<T> success() {
        return Result.success();
    }

    /**
     * 成功-携带数据
     *
     * @param data 数据
     * @param <T> 泛型标记
     * @return Result
     */
    default <T> Result<T> success(@Nullable T data) {
        return Result.success(data);
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param msg 异常msg
     * @param <T> 泛型标记
     * @return Result
     */
    default <T> Result<T> status(boolean status, String msg) {
        return Result.status(status, msg);
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param sCode 异常code码
     * @param <T> 泛型标记
     * @return Result
     */
    default <T> Result<T> status(boolean status, IResultCode sCode) {
        return Result.status(status, sCode);
    }

    /**
     * 返回失败信息，用于 web
     *
     * @param msg 失败信息
     * @param <T> 泛型标记
     * @return {Result}
     */
    default <T> Result<T> fail(String msg) {
        return Result.fail(SystemCode.FAILURE, msg);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param <T> 泛型标记
     * @return {Result}
     */
    default <T> Result<T> fail(IResultCode rCode) {
        return Result.fail(rCode);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param msg 失败信息
     * @param <T> 泛型标记
     * @return {Result}
     */
    default <T> Result<T> fail(IResultCode rCode, String msg) {
        return Result.fail(rCode, msg);
    }

    /**
     * 下载文件
     *
     * @param file 文件
     * @return {ResponseEntity}
     */
    default ResponseEntity<Resource> download(File file) {
        String fileName = file.getName();
        return download(file, fileName);
    }

    /**
     * 下载
     *
     * @param file 文件
     * @param fileName 生成的文件名
     * @return {ResponseEntity}
     */
    default ResponseEntity<Resource> download(File file, String fileName) {
        Resource resource = new FileSystemResource(file);
        return download(resource, fileName);
    }

    /**
     * 下载
     *
     * @param resource 资源
     * @param fileName 生成的文件名
     * @return {ResponseEntity}
     */
    default ResponseEntity<Resource> download(Resource resource, String fileName) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        String encodeFileName = UriUtils.encode(fileName, Charsets.UTF_8);
        String disposition = "attachment;" +
                "filename=\"" + encodeFileName + "\";" +
                "filename*=utf-8''" + encodeFileName;
        headers.set(HttpHeaders.CONTENT_DISPOSITION, disposition);
        return new ResponseEntity<>(resource, headers, HttpStatus.OK);
    }
}
